<template>
  <AdVxeModal
    v-bind="$attrs"
    :destroyOnClose="true"
    @register="registerModal"
    :showCancel="false"
    :showOk="false"
    :close-func="handleClose"
    @ok="handleOk"
  >
    <template #insertFooter>
      <a-button type="default" @click="handleCancel" :loading="loadingRef">
        {{ cancelText }}
      </a-button>
      <Authority :value="okAuthorityCode" v-if="okAuthority === true">
        <a-button type="primary" @click="handleOk" :loading="loadingRef">
          {{ okText }}
        </a-button>
      </Authority>
      <a-button type="primary" @click="handleOk" v-if="okAuthority !== true" :loading="loadingRef">
        {{ okText }}
      </a-button>
    </template>
    <BasicTree
      v-bind="$attrs"
      :toolbar="toolbar"
      :search="search"
      :checkable="checkable"
      :selectable="selectable"
      :multiple="multiple"
      :treeData="treeDataRef"
      :checkedKeys="checkedKeysRef"
      :selectedKeys="selectedKeysRef"
      ref="treeRef"
    />
  </AdVxeModal>
</template>
<script lang="ts">
  import type { PropType } from 'vue';
  import { defineComponent, ref } from 'vue';
  import { useI18n } from '@/hooks/web/useI18n';

  import { AdVxeModal, useModalInner } from '@/components/AdVxeModal';
  import { BasicTree, TreeItem, TreeActionType } from '@/components/Tree';
  import { Authority } from '@/components/Authority';

  import { isFunction } from '@/utils/is';
  import { propTypes } from '@/utils/propTypes';

  const { t } = useI18n();

  export default defineComponent({
    name: 'TreeModal',
    components: { AdVxeModal, BasicTree, Authority },
    props: {
      /** 是否显示工具栏 */
      toolbar: propTypes.bool.def(true),
      /** 显示搜索框 */
      search: propTypes.bool.def(true),
      /** 节点前添加 Checkbox 复选框 */
      checkable: propTypes.bool.def(true),
      /** 是否可选中 */
      selectable: propTypes.bool.def(true),
      /** 支持点选多个节点（节点本身） */
      multiple: propTypes.bool.def(false),
      /** 取消按钮文本 */
      cancelText: propTypes.string.def(t('common.cancelText')),
      /** 关闭回调，返回true关闭窗体 */
      closeFunc: {
        type: Function as PropType<
          (record: any, treeRef: TreeActionType | null) => Promise<boolean>
        >,
        default: null,
      },
      /** 确认按钮文本 */
      okText: propTypes.string.def(t('common.okText')),
      /** 确认按钮权限（默认不开启） */
      okAuthority: propTypes.bool.def(false),
      /** 确认按钮权限代码（按钮权限开启有效） */
      okAuthorityCode: {
        type: [Number, Array, String] as PropType<string | string[]>,
        default: '',
      },
      /** 确定回调，返回true关闭窗体 */
      okFunc: {
        type: Function as PropType<
          (record: any, treeRef: TreeActionType | null) => Promise<boolean>
        >,
        default: null,
      },
    },
    setup(props) {
      const treeRef = ref<TreeActionType | null>(null);
      const treeDataRef = ref<TreeItem[]>([]);
      const checkedKeysRef = ref<(string | number)[]>([]);
      const selectedKeysRef = ref<(string | number)[]>([]);
      const recordRef = ref<any>();

      //#region "加载状态"
      const loadingRef = ref(false);
      /** 开启加载状态 */
      function openLoading() {
        changeLoading(true);
        setModalProps({ okLoading: true, cancelLoading: true });
        loadingRef.value = true;
      }
      /** 关闭加载状态 */
      function closeLoading() {
        changeLoading(false);
        setModalProps({ okLoading: false, cancelLoading: false });
        loadingRef.value = false;
      }
      //#endregion

      const [registerModal, { setModalProps, closeModal, changeLoading }] = useModalInner(
        async (data) => {
          changeLoading(true);
          try {
            treeDataRef.value = [];
            checkedKeysRef.value = [];
            selectedKeysRef.value = [];
            recordRef.value = null;
            if (data.treeData && data.treeData.length > 0) {
              treeDataRef.value = data.treeData as TreeItem[];
            }
            if (data.checkedKeys && data.checkedKeys.length > 0) {
              checkedKeysRef.value = data.checkedKeys as (string | number)[];
            }
            if (data.selectedKeys && data.selectedKeys.length > 0) {
              selectedKeysRef.value = data.selectedKeys as (string | number)[];
            }
            if (data.record) {
              recordRef.value = data.record;
            }
          } finally {
            changeLoading(false);
          }
        },
      );

      /** 处理关闭事件 */
      async function handleClose() {
        openLoading();

        const { closeFunc } = props;
        try {
          if (closeFunc && isFunction(closeFunc)) {
            const result = await closeFunc(recordRef.value, treeRef.value);
            // console.log('closeFunc', !!result);
            return result;
          }
        } finally {
          closeLoading();
        }
        // console.log('handleClose', false);
        return true;
      }
      /** 处理关闭按钮 */
      async function handleCancel() {
        let innerClose = true;
        openLoading();
        const { closeFunc } = props;
        try {
          if (closeFunc && isFunction(closeFunc)) {
            innerClose = await closeFunc(recordRef.value, treeRef.value);
            // console.log('closeFunc', innerClose);
          }
        } finally {
          closeLoading();
        }
        // console.log('handleCancel', innerClose);
        if (innerClose) {
          closeModal();
        }
      }
      /** 处理确定按钮 */
      async function handleOk() {
        openLoading();

        const { okFunc } = props;
        try {
          if (okFunc && isFunction(okFunc)) {
            const canClose = await okFunc(recordRef.value, treeRef.value);
            if (canClose) {
              closeModal();
            }
          } else {
            closeModal();
          }
        } finally {
          closeLoading();
        }
      }

      return {
        t,
        loadingRef,
        registerModal,
        treeRef,
        treeDataRef,
        checkedKeysRef,
        selectedKeysRef,
        handleClose,
        handleCancel,
        handleOk,
      };
    },
  });
</script>
